package com.puzzlebazar.client.admin;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.puzzlebazar.client.services.SettingsServiceAsync;
import com.puzzlebazar.client.services.ServiceFactory;
import com.puzzlebazar.client.util.AsyncCallbackLock;
import com.puzzlebazar.client.util.ConnectionLock;
import com.puzzlebazar.client.util.ObservableImpl;

public class SiteModel extends ObservableImpl {

	public static SiteModel singleton = null;
	
	public static SiteModel get() {
		if( singleton == null )
			singleton = new SiteModel();
		return singleton;
	}
	
	private SiteInfo siteInfo = new SiteInfo();

	/**
	 * Construct a default settings model
	 */
	private SiteModel() {	
	}

	/**
	 * Sets the new site information (Must call update observers) 
	 * 
	 * @param siteInfo The new site information
	 */
	private void setSiteInfo(SiteInfo siteInfo) {
		this.siteInfo = siteInfo;
		setChanged();
	}
	
	
	/**
	 * Access the site information for this model
	 * 
	 * @return The site information for this model
	 */
	public SiteInfo getSiteInfo() {
		return siteInfo;
	}

	/**
	 * Extract all the site information from the server
	 * @param connectionLock Global lock to prevent application from operating before everything is loaded
	 */
	public void loadSiteInfo(final ConnectionLock connectionLock ) {
		SettingsServiceAsync settingsService = ServiceFactory.getSettingsService();
		settingsService.loadSiteInfo( new AsyncCallbackLock<SiteInfo>(connectionLock){
			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				super.onFailure(caught);
			}
			@Override
			public void onSuccess(SiteInfo result) {
				if( result != null ) {
					setSiteInfo( result );
					notifyObservers();
				}
				super.onSuccess(result);
			}
		});
	}
	
	/**
	 * Resets the entire database
	 * 
	 * @param lock The lock to use while performing this operation
	 */
	public void resetDatabase(ConnectionLock lock) {		
		
		SettingsServiceAsync settingsService = ServiceFactory.getSettingsService();
		settingsService.resetDatabase( new AsyncCallbackLock<Boolean>(lock) {
			@Override
			public void onFailure(Throwable caught) {
				super.onFailure(caught);
				failed();
			}
			@Override
			public void onSuccess(Boolean result) {
				super.onSuccess(result);
				if( !result ) failed();
			}
			private void failed() {
				Window.alert( "Database reset failed!" );
			}
		} );
	}
	/**
	 * Modify the site information
	 * Should call notify observers after this
	 * 
	 * @param callback The callback to use after performing this operation
	 */
	public void modifySiteInfo(final SiteInfo siteInfo, final AsyncCallback<Boolean> callback) {
		SettingsServiceAsync settingsService = ServiceFactory.getSettingsService();
		settingsService.modifySiteInfo( siteInfo, new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
				callback.onFailure(caught);
			}
			@Override
			public void onSuccess(Boolean result) {
				if( result ) {
					setSiteInfo( siteInfo );
					notifyObservers();
				}
				callback.onSuccess(result);
			}
		} );
		
	}
	
	/**
	 * @return True if the model contains valid settings, false if not
	 */
	public boolean isValid() {
		return siteInfo != null && siteInfo.isValid();
	}
	
}
